package com.sky.util;

/**
 * @author：sky-吴 日期：2020/4/27
 * 邮箱:
 */

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;

/**
 * Java本身，没有内置对应的Http相关的库函数
 * http处理，其他语言，都有内置的库：
 * Python有内置的urllib,urllib2等模块
 * C#有System.Net,System.Web相关库
 * 为了应对这个不利局面,  HttpClient，是Apache这个组织所发布的 完整的名称其实是：Apache HttpComponents
 *
 * Apache HttpComponents包含了两大部分：
 *
 * HttpComponents Core == HttpCore
 * 实现了一系列的底层传输的功能
 * 这些底层功能，可以用来去建立自己的client和server
 * 支持两种I/O模式：
 * 阻塞型Blocking：基于典型的Java的I/O模型
 * 非阻塞型Non-Blocking：基于Java的NIO，事件驱动型
 * 在线文档：  HttpCore Tutorial   http://hc.apache.org/httpcomponents-core-ga/tutorial/html/
 * 中文版：HttpCore-Simplified Chinese.pdf
 * 示例代码：HttpCore Examples
 * HttpComponents Client == HttpClient
 * 兼容HTTP 1.1
 * 基于HttpCore
 * 意味着：导入对应的库HttpClient库时，也要导入相关的HttpCore的库
 * 同时提供了其他功能：
 * 客户端认证功能
 * HTTP状态管理
 * HTTP连接管理
 * HttpClient是之前常用的那个：Commons HttpClient 3.x的继承者
 * 之前的HttpClient 3.x，现已废弃
 * 如果还要用之前的HttpClient 3.x，也强烈推荐你换用最新的HttpClient 4.1（或更新版本的）
 * 在线文档：
 * HttpClient Tutorial
 * 中文版：HttpClient Tutorial Simplified Chinese
 * 示例代码：HttpClient Examples
 * HttpClient还有个异步的版本：
 * Asynch HttpClient
 *
 */
public class HttpRequestUtil {

	/**
	 * 日志
	 */
	private static Logger log = LogManager.getLogger(HttpRequestUtil.class);

	/**
	 * 向指定URL发送GET方法的请求
	 * 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
	 *
	 * @param url 发送请求的URL
	 * @return URL 所代表远程资源的响应结果
	 */
	public static String sendGet(String url) {
		StringBuilder result = new StringBuilder();
		BufferedReader in = null;
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			URLConnection connection = realUrl.openConnection();
			// 设置通用的请求属性
			connection.setRequestProperty("accept", "*/*");
			connection.setRequestProperty("connection", "Keep-Alive");
			connection.setRequestProperty("user-agent",
					"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			connection.setRequestProperty("Accept-Charset", "UTF-8");
			connection.setRequestProperty("contentType", "UTF-8");
			// 建立实际的连接
			connection.connect();
			// 遍历所有的响应头字段
			// for (String key : map.keySet()) {
			// System.out.println(key + "--->" + map.get(key));
			// }
			// 定义 BufferedReader输入流来读取URL的响应
			in = new BufferedReader(new InputStreamReader(
					connection.getInputStream(), "utf-8"));
			String line;
			while ((line = in.readLine()) != null) {
				result.append(line);
			}
		} catch (Exception e) {
//			System.out.println("发送GET请求出现异常！" + e);
			result = new StringBuilder("{\"resCode\":\"1\",\"errCode\":\"1001\",\"resData\":\"\"}");
			e.printStackTrace();
			log.error("远程服务未开启", e);
		}
		// 使用finally块来关闭输入流
		finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}

		return result.toString();
	}

	/**
	 * 向指定 URL 发送POST方法的请求
	 *
	 * @param url   发送请求的 URL
	 * @param param 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
	 * @return 所代表远程资源的响应结果
	 */
	public static String sendPost(String url, String param) {

		PrintWriter printWriter = null;
		BufferedReader bufferedReader = null;
		StringBuilder result = new StringBuilder();
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			URLConnection urlConnection = realUrl.openConnection();
			// 设置通用的请求属性, 有些请求需要你填上, 否则对方可能不给服务
			//urlConntction.setRequestProperty("accept", "*/*");
			//urlConntction.setRequestProperty("connection", "Keep-Alive");
			//urlConntction.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			//urlConntction.setRequestProperty("Accept-Charset", "UTF-8");
			//urlConntction.setRequestProperty("contentType", "UTF-8");
			// 发送POST请求必须设置如下两行
			urlConnection.setDoOutput(true);
			urlConnection.setDoInput(true);
			// 获取URLConnection对象对应的输出流
			printWriter = new PrintWriter(urlConnection.getOutputStream());
			// 发送请求参数
			printWriter.print(param);
			// flush输出流的缓冲, 相当于把请求发出去
			printWriter.flush();


			// 定义BufferedReader输入流来读取URL的响应
			bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
			String line;
			while ((line = bufferedReader.readLine()) != null) {
				result.append(line);
			}
		} catch (Exception e) {
			System.out.println("发送 POST 请求出现异常！" + e);
			result = new StringBuilder("{\"resCode\":\"1\",\"errCode\":\"1001\",\"resData\":\"\"}");
			e.printStackTrace();
			log.error("远程服务未开启", e);
		}
		// 使用finally块来关闭输出流、输入流
		finally {
			try {
				if (printWriter != null) {
					printWriter.close();
				}
				if (bufferedReader != null) {
					bufferedReader.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return result.toString();
	}

	/**
	 * 向指定 URL 发送POST方法的请求
	 *
	 * @param url   发送请求的 URL
	 * @param param 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
	 * @return 所代表远程资源的响应结果
	 */
	public static String sendFile(String url, String param,
	                              BufferedInputStream bInputStream) {

		BufferedOutputStream out = null;
		BufferedReader in = null;
		StringBuilder result = new StringBuilder();
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			URLConnection conn = realUrl.openConnection();
			// 设置通用的请求属性
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent",
					"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			conn.setRequestProperty("Accept-Charset", "UTF-8");
			conn.setRequestProperty("contentType", "multipart/form-data");

			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setDoInput(true);
			// 发送参数
			StringBuffer sb = new StringBuffer();
			sb = sb.append(param);
			byte[] paramData = sb.toString().getBytes();
//			System.out.println(paramData.length);

			out = new BufferedOutputStream(conn.getOutputStream());
			out.write(paramData);

			if (bInputStream != null) {
				byte[] data = new byte[2048];
				while (bInputStream.read(data) != -1) {
					out.write(data);
				}
			}

			out.flush();
			// flush输出流的缓冲
			// 定义BufferedReader输入流来读取URL的响应
			in = new BufferedReader(
					new InputStreamReader(conn.getInputStream()));
			String line;
			while ((line = in.readLine()) != null) {
				result.append(line);
			}
		} catch (Exception e) {
//			System.out.println("发送 POST 请求出现异常！" + e);
			result = new StringBuilder("{\"resCode\":\"1\",\"errCode\":\"1001\",\"resData\":\"\"}");
			e.printStackTrace();
		}
		// 使用finally块来关闭输出流、输入流
		finally {
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
				if (bInputStream != null) {
					bInputStream.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}

		return result.toString();
	}


	public static void main(String[] args) {
		//url中 IP地址前面没有协议名称会报错. 因为Java不知道你要干什么
		//https 协议需要你有证书才行 ;
		// javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
		String s = sendPost("http://127.0.0.1:80/index/testJson", null);
	}








	/*
	 *
	 * java.net.MalformedURLException: no protocol
	 * no protocol，没有指定通信协议异常
	 * 如果是没有指定 http 协议，在 URL 前面加上http://即可解决此异常
	 * */
}



/**
 *  public static void parseJson(String jsonString){

 //创建一个 ObjectMapper 对象出来, 准备读取json
 ObjectMapper mapper = new ObjectMapper();
 //创建一个jsonNode 对象出来解析这个json
 JsonNode rootNode = null;
 try {
 rootNode = mapper.readTree(jsonString);

 JsonNode titleNode = rootNode.get("title");
 System.out.println("title: " + titleNode.textValue());

 JsonNode contentNode = rootNode.get("content");
 System.out.println("content: " + contentNode.textValue());


 } catch (JsonProcessingException e) {
 e.printStackTrace();
 }
 }
 */